package configClient;

import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;

/**
 * Config Client 基类。一个 Config Client 对应一个key
 * 提供一些基础的逻辑，区别点在于 怎么获取 configKey对应的configValue
 */

public class BaseConfigClient implements ConfigClient {

    /**
     * 配置更改回调监听器
     */
    private List<ConfigChangeListener> configChangeListeners;

    /**
     * configKey
     */
    private final String configKey;

    /**
     * 原始 config
     */
    private String oriConfig;

    /**
     * 现在 config
     */
    private String newConfig;

    /**
     * 本地 configKey 源信息
     */
    private ConfigMetaInfo localConfigMetaInfo;

    public BaseConfigClient(String configKey) {
        this.configKey = configKey;
        this.configChangeListeners = new ArrayList<>();
    }

    @Override
    public String getConfig(String configKey) {
        String remoteConfig = this.doGetConfig(configKey);
        if (isNull(remoteConfig)) {
            // 拉取失败
            return newConfig;
        }
        // 拉新配置
        newConfig = remoteConfig;
        // 回调监听器
        ofNullable(configChangeListeners)
                .ifPresent(listeners ->
                        listeners.forEach(listener -> listener.onConfigChange(oriConfig, newConfig))
                );
        return newConfig;
    }

    @Override
    public void addListenner(ConfigChangeListener configChangeListener) {
        configChangeListeners = ofNullable(configChangeListeners).orElse(new ArrayList<>());
        configChangeListeners.add(configChangeListener);
    }

    @Override
    public ConfigMetaInfo getRemoteConfigMetaInfo(String configKey) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean configChange() {
        // 远程配置元信息
        ConfigMetaInfo remoteConfigMetaInfo = getRemoteConfigMetaInfo(configKey);
        // remoteConfigMetaInfo 对不上 说明发生了更改
        boolean flag = false;
        if (nonNull(remoteConfigMetaInfo) && !remoteConfigMetaInfo.equals(localConfigMetaInfo)) {
            flag = true;
            // 本地元信息更新
            localConfigMetaInfo = remoteConfigMetaInfo;
        }
        return flag;
    }

    @Override
    public void init() {
        // 拉远程配置元信息
        localConfigMetaInfo = getRemoteConfigMetaInfo(configKey);
        // 拉取远程配置
        getConfig(configKey);
    }

    @Override
    public void rePull() {
        // old 更新为 new
        oriConfig = newConfig;
        getConfig(configKey);
    }

    /**
     * 交给子类实现
     */

    protected String doGetConfig(String configKey) {
        throw new UnsupportedOperationException();
    }

    public String getConfigKey() {
        return configKey;
    }
}
